package com.rexolar.openapi.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.rexolar.openapi.bean.request.LoginRequest;
import com.rexolar.openapi.bean.request.XsseRequest;
import com.rexolar.openapi.bean.response.LoginResponse;
import com.rexolar.openapi.common.OpenApiResult;
import com.rexolar.openapi.db.entity.PaasPartnerApp;
import com.rexolar.openapi.db.entity.SaasUserInfo;
import com.rexolar.openapi.db.mapper.SaasUserInfoMapper;
import com.rexolar.openapi.enums.ErrorCodeEnum;
import com.rexolar.openapi.enums.PartnerStatusEnum;
import com.rexolar.openapi.job.GwDeviceSyncJob;
import com.rexolar.openapi.service.RexolarApiClient;
import com.rexolar.openapi.service.impl.PartnerAppService;
import com.rexolar.openapi.utlis.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author zhusiyu11000
 * @date 2020-02-10
 **/

@RestController
@Slf4j
public class AuthController {
    @Autowired
    SaasUserInfoMapper saasUserInfoMapper;

    @Autowired
    PartnerAppService partnerAppService;

    @Autowired
    RexolarApiClient rexolarApiClient;
    @PostMapping("/xsse")
    @ResponseBody
    public OpenApiResult xsse(@RequestBody XsseRequest xsseRequest) {
        String appSecret = partnerAppService.fetchAppSecret(xsseRequest.getAppkey());
        if(StringUtils.isNotBlank(appSecret)){
            log.error("xsse appkey exist, appkey:{}", xsseRequest.getAppkey());
            return OpenApiResult.fail(ErrorCodeEnum.ILLEGAL_PARAMETERS_USER_EXIST);
        }
        LambdaQueryWrapper<SaasUserInfo> allQueryWrapper = new LambdaQueryWrapper<>();
        allQueryWrapper.eq(SaasUserInfo::getUsername, xsseRequest.getMail());
        List<SaasUserInfo> list = saasUserInfoMapper.selectList(allQueryWrapper);
        if(!CollectionUtils.isEmpty(list)){
            log.error("xsse error, mail:{}", xsseRequest.getMail());
            return OpenApiResult.fail(ErrorCodeEnum.ILLEGAL_PARAMETERS_USER_EXIST);
        }
        Map user = rexolarApiClient.authLogin(xsseRequest.getMail(), xsseRequest.getMailPassword());
        if (user == null || user.size() == 0){
            log.error("xsse user paasword error, mail:{}", xsseRequest.getMail());
            return OpenApiResult.fail(ErrorCodeEnum.ILLEGAL_PARAMETERS_USER_PASSWORD);
        }
        SaasUserInfo saasUserInfo = new SaasUserInfo();
        saasUserInfo.setMail(xsseRequest.getMail());
        saasUserInfo.setMailPassword(xsseRequest.getMailPassword());
        saasUserInfo.setPassword(xsseRequest.getMailPassword());
        saasUserInfo.setUsername(xsseRequest.getMail());
        saasUserInfo.setTenantId(xsseRequest.getTenantId());
        saasUserInfo.setType("paas");
        saasUserInfo.setCreateTime(new Date());
        saasUserInfo.setUpdateTime(new Date());
        if(saasUserInfoMapper.insert(saasUserInfo)!=1){
            return OpenApiResult.fail(ErrorCodeEnum.SYSTEM_ERROR);
        }
        PaasPartnerApp app = new PaasPartnerApp();
        app.setPartnerCode(xsseRequest.getAppkey());
        app.setPartnerSecret(xsseRequest.getAppSecret());
        app.setUserId(saasUserInfo.getId());
        app.setStatus(PartnerStatusEnum.ON.getCode());
        app.setGmtCreate(new Date());
        app.setGmtModified(new Date());

        if(!partnerAppService.save(app)){
            return OpenApiResult.fail(ErrorCodeEnum.SYSTEM_ERROR);
        }
        return OpenApiResult.success(true);
    }
    @PostMapping("/login")
    @ResponseBody
    @SentinelResource(value = "login",blockHandler = "handler_login")
    public OpenApiResult login(@RequestBody LoginRequest loginRequest) {
        String appKey = loginRequest.getAppkey();
        if(StringUtils.isBlank(appKey)){
            log.error("login 缺少必选参数, loginRequest:{}", loginRequest);
            return new OpenApiResult(ErrorCodeEnum.LESS_PARAMETERS.getCode(), ErrorCodeEnum.LESS_PARAMETERS.getMessage()+"appKey");
        }
        LambdaQueryWrapper<PaasPartnerApp> query = new LambdaQueryWrapper<>();
        query.eq(PaasPartnerApp::getPartnerCode, appKey);
        query.eq(PaasPartnerApp::getStatus, PartnerStatusEnum.ON.getCode());
        PaasPartnerApp partner = partnerAppService.getOne(query);
        if (partner == null){
            log.error("login error, appKey:{}", appKey);
            return new OpenApiResult(ErrorCodeEnum.USER_APP_STOP);
        }

        SaasUserInfo saasUserInfo = saasUserInfoMapper.selectById(partner.getUserId());
        if(saasUserInfo == null){
            log.error("login error, appkey:{}, userId:{}", appKey, partner.getUserId());
            return new OpenApiResult(ErrorCodeEnum.USER_APP_STOP);
        }

        Map tokenMap = rexolarApiClient.authLogin(saasUserInfo.getMail(), saasUserInfo.getMailPassword());
        if (tokenMap == null || tokenMap.size() == 0){
            log.error("AuthController login error, mail:{}, pwd:{}, result：{}", saasUserInfo.getMail(), saasUserInfo.getMailPassword(), tokenMap);
            return new OpenApiResult(ErrorCodeEnum.SYSTEM_ERROR);
        }
        /*解析token*/
        String token = (String) tokenMap.get("token");
        String refreshToken = (String) tokenMap.get("refreshToken");
        Map payload = JwtUtils.getPayload(token);

        GwDeviceSyncJob.userMap.put(saasUserInfo.getTenantId(), token);

        /*生成返回体*/
        LoginResponse loginResponse = new LoginResponse();
        loginResponse.setUser(saasUserInfo.getUsername());
        loginResponse.setToken(token);
        loginResponse.setRefreshToken(refreshToken);
        loginResponse.setUserId(payload.get("userId").toString());
        loginResponse.setAuthority(payload.get("scopes").toString());
        loginResponse.setExt(Long.parseLong(payload.get("exp").toString()));

        return OpenApiResult.success(token);
    }

}
